#include"mystdio.h"

//打开文件的声明
MY_FILE* MY_fopen(const char *path,const char*mode)
{
    int flag = 0;
    //判断mode，实现不同打开方式
    if(strcmp(mode,"r")==0)
    {
        flag |= O_RDONLY;
    }
    else if(strcmp(mode ,"w")==0)
    {
        flag |=(O_WRONLY|O_CREAT|O_TRUNC);
    }
    else if(strcmp(mode,"a")==0)
    {
        flag |=(O_WRONLY|O_CREAT|O_APPEND);
    }
    //open的第三个参数权限
    mode_t m = 0666;
    //文件打开，如果不存在就需要重新创建
    int fd = 0 ;
    if(flag & O_CREAT)
    {
        fd = open (path,flag,m);
    }
    else
    {
        fd = open(path, flag);
    }
    if(fd < 0 )
    {
        return NULL; 
    }
    MY_FILE* mf = (MY_FILE*)malloc(sizeof(MY_FILE));
    if(mf == NULL)
    {
        close(fd);
    }
    mf->fd = fd;
    //默认行刷新
    mf->flags = BUFF_LINE;
    //第一种做法：mf->outputbuffer[0]=0;
    memset(mf->outputbuffer,'\0',sizeof(mf->outputbuffer));
    mf->current = 0;
    return mf;
}
int my_fflush(MY_FILE* fp)
{
    assert(fp);
    write(fp->fd,fp->outputbuffer,fp->current);
    fp ->current =0;
    fsync(fp->fd);
    return 0 ;
}
//关闭文件的声明
int MY_fclose(MY_FILE* fp)
{
    assert(fp);
    //冲刷缓冲区
    if(fp->current > 0)
    {
        my_fflush(fp);
    }
    //关闭文件
    close(fp->fd);
    //释放堆空间
    free(fp);
    //将指针滞空
    fp = NULL;
    return 0;
}
//写文件(第一个参数表示缓冲区中的内容一会 会被写入，第二个参数表示每个大小是多大，第三个参数表示一共有多少个)
//返回写入了多少个数据块（也就是nummb,表示写了多少个size），但是自己实现的为了方便直接返回字节数
size_t MY_fwrite(const void*ptr,size_t size,size_t nummb ,MY_FILE*stream)
{
    //缓冲区满了，就把缓冲区的内容写入，刷新出去
    if(stream ->current == NUM)
    {
        my_fflush(stream);
    }
    //根据缓冲区剩余情况，进行数据拷贝
    //判断想要写入缓冲区的大小，缓冲区能不能放下
    //用户想要写入的大小
    size_t user_size = size*nummb;
    //缓冲区现在有
    size_t Buff_size = NUM - stream->current;
    //表示返回值实际写了多少字节
    size_t writen = 0;
    //缓冲区能够放下
    if(Buff_size >= user_size)
    {
        memcpy(stream->outputbuffer + stream ->current, ptr ,user_size);
        stream->current += user_size; 
        writen = user_size;
    }
    //缓冲区放不下
    else
    {
        //能拷贝多少，就拷贝多少
        memcpy(stream->outputbuffer + stream ->current, ptr ,Buff_size);
        stream->current += Buff_size; 
        writen = Buff_size;
    }
    //开始计划刷新
    //如果是全刷新
    if(stream ->flags & BUFF_ALL)
    {
        if(stream ->current == NUM)
        {
            my_fflush(stream);
        }
    }
    else if(stream ->flags & BUFF_LINE)
    {
        if(stream ->outputbuffer[stream ->current -1 ] == '\n')
        {
            my_fflush(stream);
        }
    }
    else
    {

    }
    return writen;
}
